home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Technical Documentation / Sample Code / DTS.Lib & Samples / DTS.Lib / Window.c < prev   
Encoding:
C/C++ Source or Header  |  1992-10-22  |  56.0 KB  |  2,318 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:     DTS.Lib
  5. ** File:        window.c
  6. ** Written by:  Eric Soldan
  7. **
  8. ** Copyright © 1990-1991 Apple Computer, Inc.
  9. ** All rights reserved.
  10. */
  11.  
  12.  
  13.  
  14. /*****************************************************************************/
  15.  
  16.  
  17.  
  18. #include "DTS.Lib2.h"
  19. #include "DTS.Lib.Common.h"
  20. #include "DTS.Lib.protos.h"
  21.  
  22. #ifndef __DESK__
  23. #include <Desk.h>
  24. #endif
  25.  
  26. #ifndef __ERRORS__
  27. #include <Errors.h>
  28. #endif
  29.  
  30. #ifndef __MOVIES__
  31. #include <Movies.h>
  32. #endif
  33.  
  34. #ifndef THINK_C
  35. #ifndef __SYSEQU__
  36. #include <SysEqu.h>
  37. #endif
  38. #endif
  39.  
  40. #ifndef __TOOLUTILS__
  41. #include <ToolUtils.h>
  42. #endif
  43.  
  44. #ifndef __UTILITIES__
  45. #include "Utilities.h"
  46. #endif
  47.  
  48.  
  49.  
  50. /*****************************************************************************/
  51.  
  52.  
  53.  
  54. short    gBeginUpdateNested;
  55.  
  56. static RgnHandle    gKeepUpdateRgn;
  57. static WindowPtr    gOldPort;
  58.  
  59. extern short        gPrintPage;                    /* Non-zero means we are printing. */
  60. extern short        gMinVersion, gMaxVersion;
  61. extern Boolean        gInBackground;
  62.  
  63. RgnHandle    gCursorRgn;
  64.     /* The current cursor region.  The initial cursor region is an empty
  65.     ** region, which will cause WaitNextEvent to generate a mouse-moved
  66.     ** event, which will cause us to set the cursor for the first time. */
  67.  
  68. static Cursor    gCursor;
  69. CursPtr            gCursorPtr;
  70.     /* The current cursor that applies to gCursorRgn.  These values
  71.     ** are here to shorten the re-processing time for determining the
  72.     ** correct cursor after an event.  This is specifically so that characters
  73.     ** can be typed into the TextEdit control faster.  If we spend a great
  74.     ** deal of time per-event recalculating the cursor region, text entry for
  75.     ** the TextEdit control slows down considerably.  If you want to override
  76.     ** the time savings because you are changing the cursor directly, either
  77.     ** set gCursorPtr to nil, or call DoSetCursor to set the cursor.
  78.     ** DoSetCursor simply sets gCursorPtr to nil, as well as setting
  79.     ** the cursor. */
  80.  
  81. static Rect    OldLocWindow(WindowPtr window, WindowPtr relatedWindow, Rect sizeInfo);
  82.  
  83.  
  84.  
  85. /*****************************************************************************/
  86. /*****************************************************************************/
  87.  
  88.  
  89.  
  90. /* This function creates a new application window.  An application window
  91. ** contains a document which is referenced by a handle in the refCon field. */
  92.  
  93. #pragma segment Window
  94. OSErr    DoNewWindow(FileRecHndl frHndl, WindowPtr *retWindow,
  95.                     WindowPtr relatedWindow, WindowPtr behind)
  96. {
  97.     WindowPtr            oldPort, window;
  98.     FileRecHndl            ffrHndl;
  99.     ControlHandle        ctl;
  100.     Rect                ctlRect, contRect, userState, sizeInfo;
  101.     short                attributes, h, v, wkind, wwkind;
  102.     OSErr                err;
  103.     GetDocWindowProcPtr    proc;
  104.  
  105.     if (!frHndl) return(noErr);
  106.     attributes = (*frHndl)->fileState.attributes;
  107.  
  108.     err = noErr;
  109.     GetPort(&oldPort);
  110.  
  111.     proc = (*frHndl)->fileState.getDocWindow;
  112.     if (!proc)
  113.         proc = GetStaggeredWindow;
  114.     if (attributes & kwOpenAtOldLoc)
  115.         proc = GetOldLocWindow;
  116.  
  117.     SetRect(&sizeInfo, 0, 0, 0, 0);
  118.  
  119.     wkind = (attributes & (kwIsPalette | kwIsModalDialog));
  120.     if (behind) {
  121.         for (;;) {
  122.             if (!(behind = GetNextWindow(behind, 0))) break;
  123.                 /* break if behind all windows.  behind is nil, so that's what we have. */
  124.             ffrHndl = (FileRecHndl)GetWRefCon(behind);
  125.             wwkind  = ((*ffrHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog));
  126.             if (wkind >= wwkind) {
  127.                 behind = GetPreviousWindow(behind);
  128.                 break;
  129.             }
  130.         }
  131.     }
  132.  
  133.     window = (*proc)((*frHndl)->fileState.windowID, nil, false, relatedWindow,
  134.                      behind, true, sizeInfo, (long)frHndl);
  135.     if (window) {
  136.         SetPort(window);
  137.         NewWindowTitle(window, nil);
  138.  
  139.         (*frHndl)->fileState.window = window;
  140.  
  141.         (*frHndl)->fileState.hArrowVal = 16;    /* Default arrow value is 16. */
  142.         (*frHndl)->fileState.vArrowVal = 16;
  143.  
  144.         (*frHndl)->fileState.windowSizeBounds.left   = kMinWindowWidth;
  145.         (*frHndl)->fileState.windowSizeBounds.top    = kMinWindowHeight;
  146.         (*frHndl)->fileState.windowSizeBounds.right  = kMaxWindowWidth;
  147.         (*frHndl)->fileState.windowSizeBounds.bottom = kMaxWindowHeight;
  148.             /* Default min/max window size for growIcon. */
  149.  
  150.         if (!(*frHndl)->d.doc.fhInfo.hDocSize) {
  151.             h  = window->portRect.right;
  152.             h -= (*frHndl)->fileState.leftSidebar;    /* Default document size is */
  153.             if (attributes & kwHScroll)                /* content less leftSidebar */
  154.                 h -= 15;                            /* value less scrollbars.   */
  155.             (*frHndl)->d.doc.fhInfo.hDocSize = h;
  156.         }
  157.         if (!(*frHndl)->d.doc.fhInfo.vDocSize) {
  158.             v  = window->portRect.bottom;
  159.             v -= (*frHndl)->fileState.topSidebar;    /* We don't have to initialize the page */
  160.             if (attributes & kwVScroll)                /* values since the scrollbars won't be */
  161.                 v -= 15;                            /* active until the window is resized   */
  162.             (*frHndl)->d.doc.fhInfo.vDocSize = v;    /* or these values are set elsewhere.   */
  163.         }
  164.  
  165.         if (attributes & kwHScroll) {        /* Caller wants a horizontal scrollbar... */
  166.             ctlRect = window->portRect;
  167.             ctlRect.left += (*frHndl)->fileState.leftSidebar;
  168.             ctlRect.left += (*frHndl)->fileState.hScrollIndent;
  169.             --ctlRect.left;
  170.             ++ctlRect.right;
  171.             ctlRect.top = ++ctlRect.bottom - 16;
  172.             if (attributes & (kwHScrollLessGrow - kwHScroll +  kwGrowIcon))
  173.                 ctlRect.right -= 15;
  174.             OffsetRect(&ctlRect, 0, -16384);
  175.             ctl = NewControl(window, &ctlRect, nil, true, 0, 0, 0, scrollBarProc, 0L);
  176.             if (ctl)
  177.                 (*frHndl)->fileState.hScroll = ctl;
  178.             else
  179.                 err = memFullErr;
  180.         }
  181.  
  182.         if (!err) {
  183.             if (attributes & kwVScroll) {        /* Caller wants a vertical scrollbar... */
  184.                 ctlRect = window->portRect;
  185.                 ctlRect.top += (*frHndl)->fileState.topSidebar;
  186.                 ctlRect.top += (*frHndl)->fileState.vScrollIndent;
  187.                 --ctlRect.top;
  188.                 ++ctlRect.bottom;
  189.                 ctlRect.left = ++ctlRect.right - 16;
  190.                 if (attributes & (kwVScrollLessGrow - kwVScroll +  kwGrowIcon))
  191.                     ctlRect.bottom -= 15;
  192.                 OffsetRect(&ctlRect, 0, -16384);
  193.                 ctl = NewControl(window, &ctlRect, nil, true, 0, 0, 0, scrollBarProc, 0L);
  194.                 if (ctl)
  195.                     (*frHndl)->fileState.vScroll = ctl;
  196.                 else
  197.                     err = memFullErr;
  198.             }
  199.         }
  200.  
  201.         if (!err) {
  202.             err = DoInitContent(frHndl, window);
  203.             if (!err) {
  204.                 contRect  = GetWindowContentRect(window);
  205.                 userState = mDerefWStateData(window)->userState;
  206.                     /* Cache this.  ShowWindow offscreen messes it up.  We want to keep
  207.                     ** whatever it is because some other function may be tweeking stdState
  208.                     ** and userState so that window position and zoom state can be saved
  209.                     ** along with a document. */
  210.  
  211.                 MoveWindow(window, 16384, 16384, false);
  212.                     /* When an invisible window is added, it isn't the frontmost window.
  213.                     ** This causes a problem when we make it visible.  By moving it
  214.                     ** offscreen, we can make it visible without the user seeing that it
  215.                     ** isn't the top window. */
  216.  
  217.                 if (gPrintPage) {
  218.                     ShowWindow(window);                            /* Window now visible. */
  219.                     MoveWindow(window, 16384, 16384, true);        /* Window now on top.  */
  220.                 }    /* If we are printing, we want to leave the window offscreen, since we
  221.                     ** don't want it seen.  We do need a visible window when printing so
  222.                     ** PrintMonitor can get the document name. */
  223.  
  224.                 if (!gPrintPage) {
  225.                     if (attributes & kwVisible)
  226.                         ShowHide(window, true);
  227.                     CleanSendBehind(window, behind);
  228.                     MoveWindow(window, contRect.left, contRect.top, false);
  229.                 }
  230.  
  231.                 mDerefWStateData(window)->userState = userState;
  232.                     /* The ShowWindow metrics we did cause the userState to change.  Put it
  233.                     ** back the way it was before we started messing around with the window. */
  234.  
  235.                 AdjustScrollBars(window);
  236.             }
  237.         }
  238.         if (err) {
  239.             DisposeAnyWindow(window);
  240.             (*frHndl)->fileState.window = window = nil;
  241.         }
  242.     }
  243.     else err = memFullErr;
  244.  
  245.     SetPort(oldPort);
  246.     if (retWindow)
  247.         *retWindow = window;
  248.  
  249.     return(err);
  250. }
  251.  
  252.  
  253.  
  254. /*****************************************************************************/
  255.  
  256.  
  257.  
  258. /* This function updates the window title to reflect the new document name.
  259. ** The new document name is stored in the fileState portion of the document.
  260. ** This is automatically set to 'Untitled # N' for new documents, and is
  261. ** updated when a user does a save-as.  If the window that is being opened
  262. ** should have the resource name, then set the new document name to an
  263. ** empty string prior to calling DoNewWindow.  When this is called by
  264. ** DoNewWindow, the SetWTitle will be suppressed. */
  265.  
  266. #pragma segment Window
  267. void    NewWindowTitle(WindowPtr window, StringPtr altTitle)
  268. {
  269.     FileRecHndl    frHndl;
  270.     Str255        wTitle;
  271.  
  272.     if (window) {
  273.         if (altTitle) {
  274.             pcpy(wTitle, altTitle);
  275.             SetWTitle(window, wTitle);
  276.         }
  277.         else if (frHndl = (FileRecHndl)GetWRefCon(window)) {
  278.             pcpy(wTitle, (*frHndl)->fileState.fss.name);
  279.             if (*wTitle)
  280.                 SetWTitle(window, wTitle);
  281.         }
  282.     }
  283. }
  284.  
  285.  
  286.  
  287. /*****************************************************************************/
  288.  
  289.  
  290.  
  291. /* Close all the windows.  This is called prior to quitting the application.
  292. ** This function returns true if all windows were closed.  The user may decide
  293. ** to abort a save, thus stopping the closing of the windows.  If the user
  294. ** does this, false will be returned, indicating that all windows were not
  295. ** closed after all. */
  296.  
  297. #pragma segment Window
  298. Boolean    DisposeAllWindows(void)
  299. {
  300.     WindowPtr    window, nextWindow;
  301.     FileRecHndl    frHndl;
  302.     short        attr;
  303.  
  304. #ifdef __SYSEQU__
  305.     window = *(WindowPtr *)WindowList;
  306. #else
  307.     window = (WindowPtr)WindowList;
  308. #endif
  309.  
  310.     for (;window; window = nextWindow) {
  311.  
  312.         nextWindow = (WindowPtr)(((WindowPeek)window)->nextWindow);
  313.  
  314.         if (!IsDAWindow(window)) {
  315.             frHndl = (FileRecHndl)GetWRefCon(window);
  316.             attr   = (*frHndl)->fileState.attributes;
  317.             if (attr & kwIsPalette) continue;
  318.                 /* Closing of all of the windows may be stopped at a
  319.                 ** dirty document, so don't close the palettes. */
  320.         }
  321.  
  322.         if (!DisposeOneWindow(window, kQuit)) return(false);
  323.             /* When DisposeOneWindow returns false, this means that the window
  324.             ** didn't close.  The only cause of this is if the window had a
  325.             ** document that needed saving, and the user cancelled the save.
  326.             ** If the windows succeed in getting closed, then we are
  327.             ** returned true. */
  328.     }
  329.  
  330.     return(true);
  331. }
  332.  
  333.  
  334.  
  335. /*****************************************************************************/
  336.  
  337.  
  338.  
  339. /* Closes one window.  This window may be an application window, or it may be
  340. ** a system window.  If it is an application window, it may have a document
  341. ** that needs saving. */
  342.  
  343. #pragma segment Window
  344. Boolean    DisposeOneWindow(WindowPtr window, short saveMode)
  345. {
  346.     FileRecHndl    frHndl;
  347.     short        attr;
  348.     OSErr        err;
  349.  
  350.     if (window) {
  351.         if (!IsDAWindow(window)) {
  352.             /* First, if the window is an application window, try saving
  353.             ** the document.  Remember that the user may cancel the save.
  354.             */
  355.  
  356.             if (frHndl = (FileRecHndl)GetWRefCon(window)) {
  357.  
  358.                 attr = (*frHndl)->fileState.attributes;
  359.                 if (attr & kwHideOnClose) {
  360.                     HideWindow(window);
  361.                     HiliteWindows();
  362.                     WindowGoneFixup(window);
  363.                     return(true);
  364.                 }
  365.  
  366.                 if (IsAppWindow(window)) {
  367.                     err = SaveDocument(frHndl, window, saveMode);
  368.                     if (err) {
  369.                         if (err != userCanceledErr)
  370.                             Alert(rErrorAlert, (ModalFilterProcPtr)AlertFilter);
  371.                         return(false);
  372.                     }        /* Stop closing windows on error or user cancel. */
  373.                 }
  374.  
  375.                 err = DoFreeWindow(frHndl, window);
  376.                 if (err) return(false);
  377.  
  378.                 DisposeDocument(frHndl);
  379.                     /* If everything is cool, dispose of the document. */
  380.             }
  381.         }
  382.         DisposeAnyWindow(window);
  383.         HiliteWindows();
  384.         WindowGoneFixup(window);
  385.             /* Give the application a chance to do any related tasks. */
  386.     }
  387.  
  388.     return(true);
  389. }
  390.  
  391.  
  392.  
  393. /*****************************************************************************/
  394.  
  395.  
  396.  
  397. #pragma segment Window
  398. WindowPtr    SetFilePort(FileRecHndl frHndl)
  399. {
  400.     WindowPtr    oldPort;
  401.  
  402.     GetPort(&oldPort);
  403.     if (frHndl)
  404.         SetPort((*frHndl)->fileState.window);
  405.     return(oldPort);
  406. }
  407.  
  408.  
  409.  
  410. /*****************************************************************************/
  411.  
  412.  
  413.  
  414. #pragma segment Window
  415. void    DoResizeWindow(WindowPtr window, short oldh, short oldv)
  416. {
  417.     FileRecHndl        frHndl;
  418.     WindowPtr        oldPort;
  419.     short            attributes;
  420.     Boolean            growIconSpace;
  421.     Rect            portRct, rct;
  422.     ControlHandle    hScroll, vScroll;
  423.     RgnHandle        updateRgn;
  424.  
  425.     if (!window) return;
  426.  
  427.     frHndl  = (FileRecHndl)GetWRefCon(window);
  428.     oldPort = SetFilePort(frHndl);
  429.     attributes    = (*frHndl)->fileState.attributes;
  430.     growIconSpace = (attributes & (kwGrowIcon | (kwHScrollLessGrow - kwHScroll) | (kwVScrollLessGrow - kwVScroll)));
  431.         /* growIconSpace true if window has grow icon or a blank space for one. */
  432.  
  433.     SetOrigin(0, 0);
  434.     portRct = window->portRect;
  435.  
  436.     if (growIconSpace) {
  437.         rct.left = (rct.right  = oldh) - 15;
  438.         rct.top  = (rct.bottom = oldv) - 15;
  439.         EraseRect(&rct);
  440.         InvalRect(&rct);
  441.         rct = portRct;
  442.         rct.left = rct.right  - 15;
  443.         rct.top  = rct.bottom - 15;
  444.         EraseRect(&rct);
  445.     }
  446.  
  447.     SetOrigin(0, -16384);
  448.     if (hScroll = (*frHndl)->fileState.hScroll) {
  449.         HideControl(hScroll);
  450.         rct = (*hScroll)->contrlRect;
  451.         MoveControl(hScroll, rct.left, portRct.bottom - 15 - 16384);
  452.         SizeControl(hScroll, rct.right - rct.left + (portRct.right - portRct.left - oldh), 16);
  453.     }
  454.     if (vScroll = (*frHndl)->fileState.vScroll) {
  455.         HideControl(vScroll);
  456.         rct = (*vScroll)->contrlRect;
  457.         MoveControl(vScroll, portRct.right - 15, rct.top);
  458.         SizeControl(vScroll, 16, rct.bottom - rct.top + (portRct.bottom - portRct.top - oldv));
  459.     }
  460.  
  461.     AdjustScrollBars(window);
  462.  
  463.     if (hScroll)
  464.         ShowControl(hScroll);
  465.     if (vScroll)
  466.         ShowControl(vScroll);
  467.  
  468.     SetOrigin(0, 0);
  469.     if (attributes & kwGrowIcon)
  470.         DoDrawGrowIcon(window, false, false);
  471.  
  472.     BeginContent(window);
  473.     DoResizeContent(window, oldh, oldv);
  474.     updateRgn = NewRgn();
  475.     CopyRgn(((WindowPeek)window)->updateRgn, updateRgn);
  476.     EndContent(window);
  477.     UnionRgn(updateRgn, ((WindowPeek)window)->updateRgn, ((WindowPeek)window)->updateRgn);
  478.     DisposeRgn(updateRgn);
  479.  
  480.     SetPort(oldPort);
  481. }
  482.  
  483.  
  484.  
  485. /*****************************************************************************/
  486.  
  487.  
  488.  
  489. #pragma segment Window
  490. void    DoUpdateSeparate(WindowPtr window, RgnHandle *contRgn, RgnHandle *frameRgn)
  491. {
  492.     RgnHandle    urgn, wrgn;
  493.  
  494.     *contRgn = *frameRgn = nil;
  495.     if (!window) return;
  496.  
  497.     urgn = DoCalcFrameRgn(window);
  498.     wrgn = NewRgn();
  499.  
  500.     DiffRgn(((WindowPeek)window)->updateRgn, urgn, wrgn);
  501.     if (!EmptyRgn(wrgn)) {
  502.         *contRgn = wrgn;
  503.         wrgn = NewRgn();
  504.     }
  505.     SectRgn(((WindowPeek)window)->updateRgn, urgn, wrgn);
  506.  
  507.     if (!EmptyRgn(wrgn))
  508.         *frameRgn = wrgn;
  509.     else
  510.         DisposeRgn(wrgn);
  511.  
  512.     DisposeRgn(urgn);
  513. }
  514.  
  515.  
  516.  
  517. /*****************************************************************************/
  518.  
  519.  
  520.  
  521. #pragma segment Window
  522. void    BeginContent(WindowPtr window)
  523. {
  524.     RgnHandle        updateRgn, frameRgn;
  525.     Point            contOrg;
  526.  
  527.     if (!gBeginUpdateNested++) {
  528.         GetPort(&gOldPort);
  529.         if (window) {
  530.             SetPort(window);
  531.             CopyRgn(updateRgn = ((WindowPeek)window)->updateRgn, gKeepUpdateRgn = NewRgn());
  532.             frameRgn = DoCalcFrameRgn(window);
  533.             DiffRgn(((WindowPeek)window)->contRgn, frameRgn, updateRgn);
  534.             DisposeRgn(frameRgn);
  535.             BeginUpdate(window);
  536.             GetContentOrigin(window, &contOrg);
  537.             SetOrigin(contOrg.h, contOrg.v);
  538.         }
  539.     }
  540. }
  541.  
  542.  
  543.  
  544. /*****************************************************************************/
  545.  
  546.  
  547.  
  548. #pragma segment Window
  549. void    EndContent(WindowPtr window)
  550. {
  551.     if (!--gBeginUpdateNested) {
  552.         if (window) {
  553.             EndUpdate(window);
  554.             UnionRgn(gKeepUpdateRgn, ((WindowPeek)window)->updateRgn, ((WindowPeek)window)->updateRgn);
  555.             DisposeRgn(gKeepUpdateRgn);
  556.         }
  557.         SetPort(gOldPort);
  558.     }
  559. }
  560.  
  561.  
  562.  
  563. /*****************************************************************************/
  564.  
  565.  
  566.  
  567. #pragma segment Window
  568. void    AdjustScrollBars(WindowPtr window)
  569. {
  570.     FileRecHndl            frHndl;
  571.     WindowPtr            oldPort;
  572.     ControlHandle        hScroll, vScroll;
  573.     Rect                portRct;
  574.     Point                keepOrg;
  575.     short                h, v, maxVal, val;
  576.     DocScrollBarProc    proc;
  577.  
  578.     if (!window) return;
  579.  
  580.     oldPort = SetFilePort(frHndl = (FileRecHndl)GetWRefCon(window));
  581.     portRct = window->portRect;
  582.  
  583.     keepOrg.h = portRct.left;
  584.     keepOrg.v = portRct.top;
  585.  
  586.     portRct.left += (*frHndl)->fileState.leftSidebar;
  587.     portRct.top  += (*frHndl)->fileState.topSidebar;
  588.  
  589.     hScroll = (*frHndl)->fileState.hScroll;
  590.     vScroll = (*frHndl)->fileState.vScroll;
  591.  
  592.     SetOrigin(0, -16384);
  593.  
  594.     if ((maxVal = (*frHndl)->d.doc.fhInfo.hDocSize) > 0) {
  595.         h = portRct.right - portRct.left;
  596.         if (vScroll)
  597.             h -= 15;
  598.         maxVal -= h;
  599.         if (maxVal < 0)
  600.             maxVal = 0;
  601.         if (hScroll) {
  602.             proc = (DocScrollBarProc)GetCRefCon(hScroll);
  603.             if (proc)
  604.                 (*proc)(frHndl, hScroll, kscrollHAdjust, h);
  605.             else {
  606.                 if (maxVal < (val = GetCtlValue(hScroll)))
  607.                     maxVal = val;
  608.                 if ((*hScroll)->contrlMax != maxVal) {
  609.                     (*hScroll)->contrlMax = maxVal;
  610.                     DoDraw1Control(hScroll, true);
  611.                 }
  612.                 h -= (val = (*frHndl)->fileState.hArrowVal);
  613.                 if (h < val)
  614.                     h = val;
  615.                 (*frHndl)->fileState.hPageVal = h;
  616.             }
  617.         }
  618.     }
  619.  
  620.     if ((maxVal = (*frHndl)->d.doc.fhInfo.vDocSize) > 0) {
  621.         v = portRct.bottom - portRct.top;
  622.         if (hScroll)
  623.             v -= 15;
  624.         maxVal -= v;
  625.         if (maxVal < 0)
  626.             maxVal = 0;
  627.         if (vScroll) {
  628.             proc = (DocScrollBarProc)GetCRefCon(vScroll);
  629.             if (proc)
  630.                 (*proc)(frHndl, vScroll, kscrollVAdjust, v);
  631.             else {
  632.                 if (maxVal < (val = GetCtlValue(vScroll)))
  633.                     maxVal = val;
  634.                 if ((*vScroll)->contrlMax != maxVal) {
  635.                     (*vScroll)->contrlMax = maxVal;
  636.                     DoDraw1Control(vScroll, true);
  637.                 }
  638.                 v -= (val = (*frHndl)->fileState.vArrowVal);
  639.                 if (v < val)
  640.                     v = val;
  641.                 (*frHndl)->fileState.vPageVal = v;
  642.             }
  643.         }
  644.     }
  645.  
  646.     SetOrigin(keepOrg.h, keepOrg.v);
  647.     SetPort(oldPort);
  648. }
  649.  
  650.  
  651.  
  652. /*****************************************************************************/
  653.  
  654.  
  655.  
  656. #pragma segment Window
  657. void    GetContentOrigin(WindowPtr window, Point *contOrg)
  658. {
  659.     FileRecHndl            frHndl;
  660.     ControlHandle        ctl;
  661.     DocScrollBarProc    proc;
  662.  
  663.     contOrg->h = contOrg->v = 0;
  664.  
  665.     if (window) {
  666.         frHndl = (FileRecHndl)GetWRefCon(window);
  667.         if (ctl = (*frHndl)->fileState.hScroll) {
  668.             contOrg->h = GetCtlValue(ctl);
  669.             if (proc = (DocScrollBarProc)GetCRefCon(ctl))
  670.                 contOrg->h = (*proc)(frHndl, ctl, kscrollGetHOrigin, 0);
  671.         }
  672.         if (ctl = (*frHndl)->fileState.vScroll) {
  673.             contOrg->v = GetCtlValue(ctl);
  674.             if (proc = (DocScrollBarProc)GetCRefCon(ctl))
  675.                 contOrg->v = (*proc)(frHndl, ctl, kscrollGetVOrigin, 0);
  676.         }
  677.         contOrg->h -= (*frHndl)->fileState.leftSidebar;
  678.         contOrg->v -= (*frHndl)->fileState.topSidebar;
  679.     }
  680. }
  681.  
  682.  
  683.  
  684. /*****************************************************************************/
  685.  
  686.  
  687.  
  688. #pragma segment Window
  689. void    SetContentOrigin(WindowPtr window, long newh, long newv)
  690. {
  691.     FileRecHndl        frHndl;
  692.     WindowPtr        oldPort;
  693.     ControlHandle    hScroll, vScroll;
  694.     short            topSide, leftSide, max, dh, dv;
  695.     Point            old, contOrg;
  696.     RgnHandle        updateRgn;
  697.     Rect            contRct;
  698.  
  699.     if (!window) return;
  700.  
  701.     oldPort = SetFilePort(frHndl = (FileRecHndl)GetWRefCon(window));
  702.     hScroll = (*frHndl)->fileState.hScroll;
  703.     vScroll = (*frHndl)->fileState.vScroll;
  704.     GetContentOrigin(window, &old);
  705.     GetContentRect(window, &contRct);
  706.  
  707.     SetOrigin(0, -16384);
  708.     topSide  = (*frHndl)->fileState.topSidebar;
  709.     leftSide = (*frHndl)->fileState.leftSidebar;
  710.  
  711.     if (!hScroll)
  712.         newh = kwNoChange;
  713.     if (newh != kwNoChange) {
  714.         if (newh != kwBotScroll)
  715.             newh += leftSide;
  716.         if (newh < 0)
  717.             newh = 0;
  718.         if (newh > (max = GetCtlMax(hScroll)))
  719.             newh = max;
  720.         max = (*frHndl)->d.doc.fhInfo.hDocSize - (contRct.right - contRct.left);
  721.         if (max < 0)
  722.             max = 0;
  723.         if (newh > max)
  724.             newh = max;
  725.         if ((*hScroll)->contrlValue != newh) {
  726.             (*hScroll)->contrlValue = newh;
  727.             DoDraw1Control(hScroll, true);
  728.         }
  729.         newh -= leftSide;
  730.     }
  731.  
  732.     if (!vScroll)
  733.         newv = kwNoChange;
  734.     if (newv != kwNoChange) {
  735.         if (newv != kwBotScroll)
  736.             newv += topSide;
  737.         if (newv < 0)
  738.             newv = 0;
  739.         if (newv > (max = GetCtlMax(vScroll)))
  740.             newv = max;
  741.         max = (*frHndl)->d.doc.fhInfo.vDocSize - (contRct.bottom - contRct.top);
  742.         if (max < 0)
  743.             max = 0;
  744.         if (newv > max)
  745.             newv = max;
  746.         if ((*vScroll)->contrlValue != newv) {
  747.             (*vScroll)->contrlValue = newv;
  748.             DoDraw1Control(vScroll, true);
  749.         }
  750.         newv -= topSide;
  751.     }
  752.  
  753.     AdjustScrollBars(window);
  754.  
  755.     dh = dv = 0;
  756.     if (newh != kwNoChange)
  757.         dh = old.h - newh;
  758.     if (newv != kwNoChange)
  759.         dv = old.v - newv;
  760.  
  761.     BeginContent(window);
  762.     ScrollRect(&(window->portRect), dh, dv, updateRgn = NewRgn());
  763.     EndContent(window);
  764.  
  765.     OffsetRgn(((WindowPeek)window)->updateRgn, dh, dv);
  766.         /* We want to add the scrolled-in area into the updateRgn.  We
  767.         ** also want to keep the old area.  The old update area is
  768.         ** no longer mapped to the same location, due to the scroll,
  769.         ** so offset it by the amount scrolled.  Once it is offset, we
  770.         ** can add our new update portion to the updateRgn. */
  771.  
  772.     GetContentOrigin(window, &contOrg);
  773.     SetOrigin(contOrg.h, contOrg.v);
  774.     InvalRgn(updateRgn);
  775.     DisposeRgn(updateRgn);
  776.  
  777.     SetOrigin(old.h, old.v);
  778.     SetPort(oldPort);                /* Put things back the way we found them. */
  779.  
  780.     DoScrollFrame(window, dh, dv);    /* There may be changes in the frame due to scrolling. */
  781.  
  782.     DoSetCursor(nil);                /* Cursor region may be invalid due to
  783.                                     ** content being scrolled.  Force it to
  784.                                     ** be recalculated. */
  785. }
  786.  
  787.  
  788.  
  789. /*****************************************************************************/
  790.  
  791.  
  792.  
  793. #pragma segment Window
  794. void    GetContentRect(WindowPtr window, Rect *contRct)
  795. {
  796.     FileRecHndl        frHndl;
  797.     ControlHandle    ctl;
  798.  
  799.     SetRect(contRct, 0, 0, 0, 0);
  800.  
  801.     if (window) {
  802.         frHndl = (FileRecHndl)GetWRefCon(window);
  803.         *contRct = window->portRect;
  804.         if (ctl = (*frHndl)->fileState.hScroll)
  805.             contRct->bottom -= 15;
  806.         if (ctl = (*frHndl)->fileState.vScroll)
  807.             contRct->right  -= 15;
  808.         contRct->top  += (*frHndl)->fileState.topSidebar;
  809.         contRct->left += (*frHndl)->fileState.leftSidebar;
  810.     }
  811. }
  812.  
  813.  
  814.  
  815. /*****************************************************************************/
  816.  
  817.  
  818.  
  819. #pragma segment Window
  820. void    SetDocSize(FileRecHndl frHndl, long hSize, long vSize)
  821. {
  822.     if (frHndl) {
  823.         if (hSize >= 0)
  824.             (*frHndl)->d.doc.fhInfo.hDocSize = hSize;
  825.         if (vSize >= 0)
  826.             (*frHndl)->d.doc.fhInfo.vDocSize = vSize;
  827.         AdjustScrollBars((*frHndl)->fileState.window);
  828.     }
  829. }
  830.  
  831.  
  832.  
  833. /*****************************************************************************/
  834.  
  835.  
  836.  
  837. #pragma segment Window
  838. void    SetSidebarSize(FileRecHndl frHndl, short newLeft, short newTop)
  839. {
  840.     WindowPtr            oldPort, window;
  841.     Rect                portRct, rct;
  842.     Point                contOrg;
  843.     short                oldLeft, oldTop, dh, dv;
  844.     ControlHandle        ctl;
  845.     RgnHandle            updateRgn;
  846.     DrawFrameProcPtr    proc;
  847.  
  848.     if (window = (*frHndl)->fileState.window) {
  849.         oldPort = SetFilePort(frHndl);
  850.         portRct = window->portRect;
  851.         SetOrigin(0, -16384);        /* Prepare to modify (redraw) document scrollbars. */
  852.     }
  853.  
  854.     oldLeft = (*frHndl)->fileState.leftSidebar;
  855.     oldTop  = (*frHndl)->fileState.topSidebar;
  856.  
  857.     dh = 0;
  858.     if (newLeft != kwNoChange) {
  859.         if (ctl = (*frHndl)->fileState.hScroll) {
  860.             HideControl(ctl);
  861.             rct = (*ctl)->contrlRect;
  862.             rct.left += (newLeft - oldLeft);
  863.             MoveControl(ctl, rct.left, rct.top);
  864.             SizeControl(ctl, rct.right - rct.left, 16);
  865.             ShowControl(ctl);
  866.         }
  867.         dh = newLeft - oldLeft;
  868.     }
  869.  
  870.     dv = 0;
  871.     if (newTop != kwNoChange) {
  872.         if (ctl = (*frHndl)->fileState.vScroll) {
  873.             HideControl(ctl);
  874.             rct = (*ctl)->contrlRect;
  875.             rct.top += (newTop - oldTop);
  876.             MoveControl(ctl, rct.left, rct.top);
  877.             SizeControl(ctl, 16, rct.bottom - rct.top);
  878.             ShowControl(ctl);
  879.         }
  880.         dv = newTop - oldTop;
  881.     }
  882.  
  883.     if (dh < 0)
  884.         (*frHndl)->fileState.leftSidebar = newLeft;
  885.     if (dv < 0)
  886.         (*frHndl)->fileState.topSidebar  = newTop;
  887.  
  888.     if (window) {
  889.         BeginContent(window);
  890.         ScrollRect(&(window->portRect), dh, dv, updateRgn = NewRgn());
  891.         EndContent(window);
  892.     }
  893.  
  894.     if (dh)
  895.         (*frHndl)->fileState.leftSidebar = newLeft;
  896.     if (dv)
  897.         (*frHndl)->fileState.topSidebar  = newTop;
  898.  
  899.     if (window) {
  900.         if (proc = (*frHndl)->fileState.drawFrameProc) {
  901.             SetOrigin(0, 0);
  902.             (*proc)(frHndl, window);        /* Draw the application's portion of the frame. */
  903.         }
  904.         OffsetRgn(((WindowPeek)window)->updateRgn, dh, dv);
  905.             /* We want to add the scrolled-in area into the updateRgn.  We
  906.             ** also want to keep the old area.  The old update area is
  907.             ** no longer mapped to the same location, due to the scroll,
  908.             ** so offset it by the amount scrolled.  Once it is offset, we
  909.             ** can add our new update portion to the updateRgn. */
  910.         GetContentOrigin(window, &contOrg);
  911.         SetOrigin(contOrg.h, contOrg.v);
  912.         InvalRgn(updateRgn);
  913.         DisposeRgn(updateRgn);
  914.  
  915.         SetOrigin(portRct.left, portRct.top);
  916.         SetPort(oldPort);
  917.  
  918.         DoScrollFrame(window, dh, dv);        /* There may be changes in the frame due to scrolling. */
  919.     }
  920. }
  921.  
  922.  
  923.  
  924. /*****************************************************************************/
  925.  
  926.  
  927.  
  928. #pragma segment Window
  929. void    SetScrollIndentSize(FileRecHndl frHndl, short newh, short newv)
  930. {
  931.     WindowPtr            oldPort, window;
  932.     Rect                portRct, rct;
  933.     short                oldh, oldv;
  934.     ControlHandle        ctl;
  935.     DrawFrameProcPtr    proc;
  936.  
  937.     oldPort = SetFilePort(frHndl);
  938.     GetPort(&window);
  939.     portRct = window->portRect;
  940.     SetOrigin(0, -16384);
  941.  
  942.     oldh = (*frHndl)->fileState.hScrollIndent;
  943.     oldv = (*frHndl)->fileState.vScrollIndent;
  944.  
  945.     if (newh != kwNoChange) {
  946.         if (ctl = (*frHndl)->fileState.hScroll) {
  947.             HideControl(ctl);
  948.             rct = (*ctl)->contrlRect;
  949.             rct.left += (newh - oldh);
  950.             MoveControl(ctl, rct.left, rct.top);
  951.             SizeControl(ctl, rct.right - rct.left, 16);
  952.             ShowControl(ctl);
  953.         }
  954.         (*frHndl)->fileState.hScrollIndent = newh;
  955.     }
  956.  
  957.     if (newv != kwNoChange) {
  958.         if (ctl = (*frHndl)->fileState.vScroll) {
  959.             HideControl(ctl);
  960.             rct = (*ctl)->contrlRect;
  961.             rct.top += (newv - oldv);
  962.             MoveControl(ctl, rct.left, rct.top);
  963.             SizeControl(ctl, 16, rct.bottom - rct.top);
  964.             ShowControl(ctl);
  965.         }
  966.         (*frHndl)->fileState.vScrollIndent = newv;
  967.     }
  968.  
  969.     if (proc = (*frHndl)->fileState.drawFrameProc) {
  970.         SetOrigin(0, 0);
  971.         (*proc)(frHndl, window);        /* Draw the application's portion of the frame. */
  972.     }
  973.  
  974.     SetOrigin(portRct.left, portRct.top);
  975.     SetPort(oldPort);
  976. }
  977.  
  978.  
  979.  
  980. /*****************************************************************************/
  981.  
  982.  
  983.  
  984. #pragma segment Window
  985. FileRecHndl    GetNextDocument(WindowPtr window, OSType sftype)
  986. {
  987.     if (!(window = GetNextWindow(window, sftype))) return(nil);
  988.     return((FileRecHndl)GetWRefCon(window));
  989. }
  990.  
  991.  
  992.  
  993. /*****************************************************************************/
  994.  
  995.  
  996.  
  997. #pragma segment Window
  998. WindowPtr    GetNextWindow(WindowPtr window, OSType sftype)
  999. {
  1000.     WindowPeek    wpeek;
  1001.     FileRecHndl    frHndl;
  1002.  
  1003.     if (window == (WindowPtr)-1)
  1004.         window = nil;
  1005.  
  1006.     if (!window)
  1007. #ifdef __SYSEQU__
  1008.         wpeek = *(WindowPeek *)WindowList;
  1009. #else
  1010.         wpeek = WindowList;
  1011. #endif
  1012.     else wpeek = ((WindowPeek)window)->nextWindow;
  1013.  
  1014.     for (; wpeek; wpeek = wpeek->nextWindow) {
  1015.  
  1016.         if (wpeek->visible) {
  1017.  
  1018.             if ((wpeek->windowKind < userKind) && (wpeek->windowKind != dialogKind)) continue;
  1019.                 /* Not a dialog or user window, so skip it. */
  1020.  
  1021.             if (!sftype) break;
  1022.                 /* Request is for any visible window.  We have a visible window, so break. */
  1023.  
  1024.             if (!(frHndl = (FileRecHndl)GetWRefCon((WindowPtr)wpeek))) {
  1025.  
  1026.                 /* Window doesn't have an frHndl in the refcon, so there is only so much that
  1027.                 ** we can check.  See if the request is specific to dialogs or regular windows.
  1028.                 ** If so, then return the window. */
  1029.  
  1030.                 if (sftype == 'DLOG')
  1031.                     if (wpeek->windowKind == dialogKind) break;
  1032.  
  1033.                 if (sftype == 'WIND')
  1034.                     if (wpeek->windowKind >= userKind) break;
  1035.  
  1036.                 continue;        /* Doesn't match request, so try next window. */
  1037.             }
  1038.             if ((*frHndl)->fileState.sfType == sftype) break;        /* Bingo. */
  1039.                 /* The sfType field is the first 4 bytes in the refcon handle.  If you don't
  1040.                 ** want to use the application framework completely, but you still want this
  1041.                 ** function, then all you have to do is place an identifier in the first 4
  1042.                 ** bytes of the refcon handle. */
  1043.         }
  1044.     }
  1045.  
  1046.     return((WindowPtr)wpeek);
  1047. }
  1048.  
  1049.  
  1050.  
  1051. /*****************************************************************************/
  1052.  
  1053.  
  1054.  
  1055. #pragma segment Window
  1056. WindowPtr    GetPreviousWindow(WindowPtr window)
  1057. {
  1058.     WindowPeek    wpeek;
  1059.     WindowPtr    lastVisWindow;
  1060.  
  1061.     if (window == (WindowPtr)-1) return((WindowPtr)-1);
  1062.  
  1063. #ifdef __SYSEQU__
  1064.     wpeek = *(WindowPeek *)WindowList;
  1065. #else
  1066.     wpeek = WindowList;
  1067. #endif
  1068.  
  1069.     for (lastVisWindow = (WindowPtr)-1; wpeek; wpeek = wpeek->nextWindow) {
  1070.         if (window == (WindowPtr)wpeek) break;
  1071.         if (wpeek->visible)
  1072.             lastVisWindow = (WindowPtr)wpeek;
  1073.     }
  1074.  
  1075.     return(lastVisWindow);
  1076. }
  1077.  
  1078.  
  1079.  
  1080. /*****************************************************************************/
  1081.  
  1082.  
  1083.  
  1084. #pragma segment Window
  1085. void    DoZoomWindow(WindowPtr window, EventRecord *event, short zoomDir)
  1086. {
  1087.     Boolean        doit;
  1088.     Rect        old;
  1089.     FileRecHndl    frHndl;
  1090.     short        hDocSize, vDocSize;
  1091.  
  1092.     doit = true;
  1093.     if (event)
  1094.         doit = TrackBox(window, event->where, zoomDir);
  1095.  
  1096.     if (doit) {
  1097.         old    = GetWindowContentRect(window);
  1098.         frHndl = (FileRecHndl)GetWRefCon(window);
  1099.         hDocSize  = (*frHndl)->d.doc.fhInfo.hDocSize;
  1100.         hDocSize += (*frHndl)->fileState.leftSidebar;
  1101.         if ((*frHndl)->fileState.hScroll)
  1102.             hDocSize += 15;
  1103.         vDocSize  = (*frHndl)->d.doc.fhInfo.vDocSize;
  1104.         vDocSize += (*frHndl)->fileState.topSidebar;
  1105.         if ((*frHndl)->fileState.vScroll)
  1106.             vDocSize += 15;
  1107.         ZoomToWindowDevice(window, hDocSize, vDocSize, zoomDir, false);
  1108.         DoResizeWindow(window, old.right - old.left, old.bottom - old.top);
  1109.     }
  1110. }
  1111.  
  1112.  
  1113.  
  1114. /*****************************************************************************/
  1115. /*****************************************************************************/
  1116.  
  1117.  
  1118.  
  1119. #pragma segment Window
  1120. RgnHandle    DoCalcFrameRgn(WindowPtr window)
  1121. {
  1122.     FileRecHndl            frHndl;
  1123.     WindowPtr            oldPort;
  1124.     RgnHandle            urgn, wrgn;
  1125.     short                i;
  1126.     Rect                rct;
  1127.     Point                l2g;
  1128.     CalcFrameRgnProcPtr    proc;
  1129.  
  1130.     urgn = NewRgn();
  1131.     if (!window) return(urgn);
  1132.  
  1133.     frHndl  = (FileRecHndl)GetWRefCon(window);
  1134.     oldPort = SetFilePort(frHndl);
  1135.     SetOrigin(0, 0);
  1136.  
  1137.     if (proc = (*frHndl)->fileState.calcFrameRgnProc)
  1138.         (*proc)(frHndl, window, urgn);
  1139.  
  1140.     wrgn = NewRgn();
  1141.     for (i = 0; i < 2; ++i) {
  1142.         rct = window->portRect;
  1143.         if (i)
  1144.             rct.bottom = (*frHndl)->fileState.topSidebar;
  1145.         else
  1146.             rct.right  = (*frHndl)->fileState.leftSidebar;
  1147.         RectRgn(wrgn, &rct);
  1148.         UnionRgn(urgn, wrgn, urgn);
  1149.     }
  1150.     DisposeRgn(wrgn);
  1151.  
  1152.     l2g.h = l2g.v = 0;
  1153.     LocalToGlobal(&l2g);
  1154.     OffsetRgn(urgn, l2g.h, l2g.v);
  1155.  
  1156.     wrgn = DoCalcScrollRgn(window);
  1157.     UnionRgn(urgn, wrgn, urgn);
  1158.     DisposeRgn(wrgn);
  1159.  
  1160.     SetPort(oldPort);
  1161.     return(urgn);
  1162. }
  1163.  
  1164.  
  1165.  
  1166. /*****************************************************************************/
  1167.  
  1168.  
  1169.  
  1170. #pragma segment Window
  1171. RgnHandle    DoCalcScrollRgn(WindowPtr window)
  1172. {
  1173.     FileRecHndl            frHndl;
  1174.     WindowPtr            oldPort;
  1175.     RgnHandle            urgn, wrgn;
  1176.     short                attributes, i;
  1177.     Boolean                growIconSpace;
  1178.     Rect                rct;
  1179.     Point                l2g;
  1180.     ControlHandle        ctl;
  1181.  
  1182.     urgn = NewRgn();
  1183.     if (!window) return(urgn);
  1184.  
  1185.     frHndl  = (FileRecHndl)GetWRefCon(window);
  1186.     oldPort = SetFilePort(frHndl);
  1187.     SetOrigin(0, 0);
  1188.  
  1189.     attributes    = (*frHndl)->fileState.attributes;
  1190.     growIconSpace = (attributes & (kwGrowIcon | (kwHScrollLessGrow - kwHScroll) | (kwVScrollLessGrow - kwVScroll)));
  1191.         /* growIconSpace true if window has grow icon or a blank space for one. */
  1192.  
  1193.     wrgn = NewRgn();
  1194.     if (growIconSpace) {
  1195.         rct = window->portRect;
  1196.         rct.left = rct.right  - 15;
  1197.         rct.top  = rct.bottom - 15;
  1198.         RectRgn(wrgn, &rct);
  1199.         UnionRgn(urgn, wrgn, urgn);
  1200.     }
  1201.     for (i = 0; i < 2; ++i) {
  1202.         ctl = (i) ? (*frHndl)->fileState.vScroll : (*frHndl)->fileState.hScroll;
  1203.         if (ctl) {
  1204.             rct = (*ctl)->contrlRect;
  1205.             if (i)
  1206.                 rct.top  -= (*frHndl)->fileState.vScrollIndent;
  1207.             else
  1208.                 rct.left -= (*frHndl)->fileState.hScrollIndent;
  1209.             OffsetRect(&rct, 0, 16384);
  1210.             RectRgn(wrgn, &rct);
  1211.             UnionRgn(urgn, wrgn, urgn);
  1212.         }
  1213.     }
  1214.     DisposeRgn(wrgn);
  1215.  
  1216.     l2g.h = l2g.v = 0;
  1217.     LocalToGlobal(&l2g);
  1218.     OffsetRgn(urgn, l2g.h, l2g.v);
  1219.  
  1220.     SetPort(oldPort);
  1221.     return(urgn);
  1222. }
  1223.  
  1224.  
  1225.  
  1226. /*****************************************************************************/
  1227.  
  1228.  
  1229.  
  1230. #pragma segment Window
  1231. void    DoContentClick(WindowPtr window, EventRecord *event, Boolean firstClick)
  1232. {
  1233.     FileRecHndl            frHndl;
  1234.     ContentClickProcPtr    proc;
  1235.  
  1236.     if (!IsDAWindow(window))
  1237.         if (frHndl = (FileRecHndl)GetWRefCon(window))
  1238.             if (proc = (*frHndl)->fileState.contentClickProc)
  1239.                 (*proc)(window, event, firstClick);
  1240. }
  1241.  
  1242.  
  1243.  
  1244. /*****************************************************************************/
  1245.  
  1246.  
  1247.  
  1248. #pragma segment Window
  1249. void    DoDragWindow(WindowPtr window, EventRecord *event, Rect bounds)
  1250. {
  1251.  
  1252.     WindowPtr    oldPort, fwindow;
  1253.     GrafPort    bigPort;
  1254.     WindowPeek    wpeek;
  1255.     FileRecHndl    frHndl;
  1256.     RgnHandle    dragRgn;
  1257.     Point        offset;
  1258.     Rect        contRct;
  1259.     short        wkind;
  1260.  
  1261.     GetPort(&oldPort);
  1262.  
  1263.     OpenPort(&bigPort);
  1264.     CopyRgn(GetGrayRgn(), bigPort.visRgn);
  1265.     bigPort.portRect = (*bigPort.visRgn)->rgnBBox;
  1266.  
  1267.     fwindow = (WindowPtr)-1;
  1268.     if (!IsDAWindow(window)) {
  1269.         frHndl  = (FileRecHndl)GetWRefCon(window);
  1270.         wkind   = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  1271.         fwindow = FrontWindowOfType(wkind);
  1272.         for (wpeek = (WindowPeek)FrontWindow(); wpeek; wpeek = wpeek->nextWindow) {
  1273.             if (fwindow == (WindowPtr)wpeek) break;
  1274.             DiffRgn(bigPort.visRgn, wpeek->strucRgn, bigPort.visRgn);
  1275.         }
  1276.     }
  1277.  
  1278.     CopyRgn(((WindowPeek)window)->strucRgn, dragRgn = NewRgn());
  1279.     *(long *)&offset = DragGrayRgn(dragRgn, event->where, &bounds, &bounds, noConstraint, nil);
  1280.  
  1281.     DisposeRgn(dragRgn);
  1282.     ClosePort(&bigPort);
  1283.     SetPort(oldPort);
  1284.  
  1285.     if ((offset.h != 0x8000) || (offset.v != 0x8000)) {
  1286.         contRct = (*((WindowPeek)window)->contRgn)->rgnBBox;
  1287.         OffsetRect(&contRct, offset.h, offset.v);
  1288.         MoveWindow(window, contRct.left, contRct.top, false);
  1289.     }
  1290.  
  1291.     if (!(event->modifiers & cmdKey))
  1292.         CleanSendInFront(window, fwindow);
  1293. }
  1294.  
  1295.  
  1296.  
  1297. /*****************************************************************************/
  1298.  
  1299.  
  1300.  
  1301. #pragma segment Window
  1302. void    DoDrawFrame(WindowPtr window)
  1303. {
  1304.     FileRecHndl            frHndl;
  1305.     WindowPtr            oldPort;
  1306.     short                attributes;
  1307.     DrawFrameProcPtr    proc;
  1308.  
  1309.     if (window) {
  1310.         frHndl  = (FileRecHndl)GetWRefCon(window);
  1311.         oldPort = SetFilePort(frHndl);
  1312.         SetOrigin(0, 0);
  1313.  
  1314.         attributes = (*frHndl)->fileState.attributes;
  1315.         if (attributes & kwGrowIcon)
  1316.             DoDrawGrowIcon(window, false, false);
  1317.  
  1318.         SetOrigin(0, -16384);
  1319.         DoDrawControls(window, true);
  1320.         SetOrigin(0, 0);
  1321.         if (proc = (*frHndl)->fileState.drawFrameProc)
  1322.             (*proc)(frHndl, window);
  1323.  
  1324.         SetPort(oldPort);
  1325.     }
  1326. }
  1327.  
  1328.  
  1329.  
  1330. /*****************************************************************************/
  1331.  
  1332.  
  1333.  
  1334. #pragma segment Window
  1335. OSErr    DoFreeDocument(FileRecHndl frHndl)
  1336. {
  1337.     FreeDocumentProcPtr    proc;
  1338.     OSErr                err;
  1339.  
  1340.     err = noErr;
  1341.     if (proc = (*frHndl)->fileState.freeDocumentProc)
  1342.         err = (*proc)(frHndl);
  1343.     return(err);
  1344. }
  1345.  
  1346.  
  1347.  
  1348. /*****************************************************************************/
  1349.  
  1350.  
  1351.  
  1352. #pragma segment Window
  1353. OSErr    DoFreeWindow(FileRecHndl frHndl, WindowPtr window)
  1354. {
  1355.     FreeWindowProcPtr    proc;
  1356.     OSErr                err;
  1357.  
  1358.     err = noErr;
  1359.     if (proc = (*frHndl)->fileState.freeWindowProc)
  1360.         err = (*proc)(frHndl, window);
  1361.     return(err);
  1362. }
  1363.  
  1364.  
  1365.  
  1366. /*****************************************************************************/
  1367.  
  1368.  
  1369.  
  1370. #pragma segment Window
  1371. OSErr    DoImageDocument(FileRecHndl frHndl)
  1372. {
  1373.     ImageProcPtr    proc;
  1374.     OSErr            err;
  1375.  
  1376.     err = noErr;
  1377.     if (proc = (*frHndl)->fileState.imageProc)
  1378.         err = (*proc)(frHndl);
  1379.     return(err);
  1380. }
  1381.  
  1382.  
  1383.  
  1384. /*****************************************************************************/
  1385.  
  1386.  
  1387.  
  1388. #pragma segment Window
  1389. OSErr    DoInitContent(FileRecHndl frHndl, WindowPtr window)
  1390. {
  1391.     InitContentProcPtr    proc;
  1392.     OSErr                err;
  1393.  
  1394.     err = noErr;
  1395.     if (proc = (*frHndl)->fileState.initContentProc)
  1396.         err = (*proc)(frHndl, window);
  1397.     return(err);
  1398. }
  1399.  
  1400.  
  1401.  
  1402. /*****************************************************************************/
  1403.  
  1404.  
  1405.  
  1406. #pragma segment Window
  1407. Boolean    DoKeyDown(EventRecord *event)
  1408. {
  1409.     char                key;
  1410.     WindowPtr            window;
  1411.     FileRecHndl            frHndl;
  1412.     ContentKeyProcPtr    proc;
  1413.     Boolean                passThrough;
  1414.  
  1415.     key = event->message & charCodeMask;
  1416.     if (event->modifiers & cmdKey) {        /* If command key down... */
  1417.         if (event->what == keyDown) {
  1418.             DoAdjustMenus();                /* Prepare menus properly. */
  1419.             DoMenuCommand(MenuKey(key));
  1420.         }
  1421.         return(false);
  1422.     }
  1423.  
  1424.     for (window = nil; window = GetNextWindow(window, 0);) {
  1425.         if (frHndl = (FileRecHndl)GetWRefCon(window)) {
  1426.             if (proc = (*frHndl)->fileState.contentKeyProc) {
  1427.                 passThrough = false;
  1428.                 if ((*proc)(window, event, &passThrough)) return(true);
  1429.                 if (!passThrough) break;
  1430.             }
  1431.         }
  1432.     }
  1433.  
  1434.     return(false);
  1435. }
  1436.  
  1437.  
  1438.  
  1439. /*****************************************************************************/
  1440.  
  1441.  
  1442.  
  1443. #pragma segment Window
  1444. void    DoMouseDown(EventRecord *event)
  1445. {
  1446.     WindowPtr    window, fwindow;
  1447.     FileRecHndl    frHndl;
  1448.     Rect        contentRct, old, growLimits;
  1449.     Point        pt;
  1450.     long        size;
  1451.     short        part, wkind;
  1452.  
  1453.     gCursorPtr = nil;
  1454.         /* No shortcuts when we recalculate the cursor region. */
  1455.  
  1456.     part = FindWindow(event->where, &window);
  1457.  
  1458.     frHndl = nil;
  1459.     if (window)
  1460.         frHndl = (FileRecHndl)GetWRefCon(window);
  1461.  
  1462.     if (part == inGrow)
  1463.         if (!((*frHndl)->fileState.attributes & kwGrowIcon))
  1464.             part = inContent;
  1465.  
  1466.     if (part != inContent)
  1467.         DoSetCursor(&qd.arrow);
  1468.  
  1469.     switch(part) {
  1470.  
  1471.         case inContent:
  1472.  
  1473.             if (IsDAWindow(window)) {
  1474.                 if (window != FrontWindow()) {
  1475.                     SelectWindow(window);
  1476.                     HiliteWindows();
  1477.                 }
  1478.                 break;
  1479.             }
  1480.  
  1481.             wkind   = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  1482.             fwindow = FrontWindowOfType(wkind);
  1483.                 /* fwindow guaranteed, since worst case we find ourself. */
  1484.  
  1485.             if (window == fwindow) {
  1486.                 DoContentClick(window, event, false);
  1487.                 break;
  1488.             }        /* The window is the frontmost of this type, so handle the click. */
  1489.  
  1490.             CleanSendInFront(window, fwindow);
  1491.  
  1492.             if ((*frHndl)->fileState.attributes & kwDoFirstClick) {
  1493.                 DoUpdate(window);
  1494.                 contentRct = GetWindowContentRect(window);
  1495.                 if (PtInRect(event->where, &contentRct))
  1496.                     DoContentClick(window, event, true);
  1497.             }
  1498.             break;
  1499.  
  1500.         case inDrag:
  1501.             DoDragWindow(window, event, qd.screenBits.bounds);
  1502.             break;        /* Pass screenBits.bounds to get all gDevices. */
  1503.  
  1504.         case inGoAway:
  1505.             if (TrackGoAway(window, event->where))
  1506.                 DisposeOneWindow(window, kClose);
  1507.             break;
  1508.  
  1509.         case inGrow:
  1510.             old = GetWindowContentRect(window);
  1511.             growLimits = (*frHndl)->fileState.windowSizeBounds;
  1512.             ++growLimits.right;
  1513.             ++growLimits.bottom;
  1514.             if (size = GrowWindow(window, event->where, &growLimits)) {
  1515.                 pt = *(Point *)&size;
  1516.                 SizeWindow(window, pt.h, pt.v, true);
  1517.                 DoResizeWindow(window, old.right - old.left, old.bottom - old.top);
  1518.             }
  1519.             break;
  1520.  
  1521.         case inMenuBar:        /* Process mouse menu command (if any). */
  1522.             DoAdjustMenus();
  1523.             DoMenuCommand(MenuSelect(event->where));
  1524.             break;
  1525.  
  1526.         case inSysWindow:    /* Let the system handle the mouseDown. */
  1527.             SystemClick(event, window);
  1528.             break;
  1529.  
  1530.         case inZoomIn:
  1531.         case inZoomOut:
  1532.             DoZoomWindow(window, event, part);
  1533.             break;
  1534.  
  1535.     }
  1536. }
  1537.  
  1538.  
  1539.  
  1540. /*****************************************************************************/
  1541.  
  1542.  
  1543.  
  1544. /* Frees up the hierarchical document and undo portions of a default document. */
  1545.  
  1546. #pragma segment Window
  1547. OSErr    DefaultFreeDocument(FileRecHndl frHndl)
  1548. {
  1549.     TreeObjHndl    root, undo;
  1550.  
  1551.     if (root = (*frHndl)->d.doc.root) {            /* If we have a valid root object... */
  1552.         if (undo = mDerefRoot(root)->undo)        /* If we have a valid undo object... */
  1553.             DisposeObjAndOffspring(undo);        /* Dispose of undo info. */
  1554.         DisposeObjAndOffspring(root);            /* Dispose of hierarchical file data. */
  1555.         (*frHndl)->d.doc.root = nil;
  1556.     }
  1557.     return(noErr);
  1558. }
  1559.  
  1560.  
  1561.  
  1562. /*****************************************************************************/
  1563.  
  1564.  
  1565.  
  1566. #pragma segment Window
  1567. OSErr    DoReadDocument(FileRecHndl frHndl)
  1568. {
  1569.     ReadDocumentProcPtr    proc;
  1570.     OSErr                err;
  1571.  
  1572.     err = noErr;
  1573.     if (proc = (*frHndl)->fileState.readDocumentProc)
  1574.         err = (*proc)(frHndl);
  1575.     return(err);
  1576. }
  1577.  
  1578.  
  1579.  
  1580. /*****************************************************************************/
  1581.  
  1582.  
  1583.  
  1584. #pragma segment Window
  1585. OSErr    DoReadDocumentHeader(FileRecHndl frHndl)
  1586. {
  1587.     ReadDocumentHeaderProcPtr    proc;
  1588.     OSErr                        err;
  1589.  
  1590.     err = noErr;
  1591.     if (proc = (*frHndl)->fileState.readDocumentHeaderProc)
  1592.         err = (*proc)(frHndl);
  1593.     return(err);
  1594. }
  1595.  
  1596.  
  1597.  
  1598. /*****************************************************************************/
  1599.  
  1600.  
  1601.  
  1602. #pragma segment Window
  1603. OSErr    DefaultReadDocument(FileRecHndl frHndl)
  1604. {
  1605.     OSErr        err;
  1606.     TreeObjHndl    root, undo;
  1607.     short        resID, refNum, flags;
  1608.     Movie        movie;
  1609.     Boolean        wasChanged;
  1610.  
  1611.     refNum = (*frHndl)->fileState.refNum;
  1612.     err    = SetFPos(refNum, fsFromStart, 0);
  1613.         /* Set the file position to the beginning of the file. */
  1614.  
  1615.     err = DoReadDocumentHeader(frHndl);
  1616.  
  1617.     if (!err) {
  1618.         if ((*frHndl)->fileState.sfType == MovieFileType) {
  1619.             resID  = 0;
  1620.             flags  = (*frHndl)->fileState.movieFlags;
  1621.             err = NewMovieFromFile(&movie, refNum, &resID, nil, flags, &wasChanged);
  1622.             if (err) return(err);
  1623.             (*frHndl)->fileState.movie                  = movie;
  1624.             (*frHndl)->fileState.movieResID             = resID;
  1625.             (*frHndl)->fileState.movieDataRefWasChanged = wasChanged;
  1626.         }
  1627.         else {
  1628.             root = (*frHndl)->d.doc.root;        /* Preserve the undo field.  Preserving  */
  1629.             undo = mDerefRoot(root)->undo;        /* any application-sepcific fields is up */
  1630.                                                 /* to the application.                     */
  1631.             err = ReadTree(root, refNum);
  1632.                 /* Read in the hierarchical file data portion. */
  1633.  
  1634.             mDerefRoot(root)->undo   = undo;    /* Restore the 2 over-written fields. */
  1635.             mDerefRoot(root)->frHndl = frHndl;
  1636.         }
  1637.     }
  1638.  
  1639.     return(err);
  1640. }
  1641.  
  1642.  
  1643.  
  1644. /*****************************************************************************/
  1645.  
  1646.  
  1647.  
  1648. #pragma segment Window
  1649. OSErr    DefaultReadDocumentHeader(FileRecHndl frHndl)
  1650. {
  1651.     short    refNum, vers;
  1652.     OSErr    err;
  1653.     char    hstate;
  1654.     Ptr        ptr1, ptr2;
  1655.     long    count;
  1656.  
  1657.     if (err = SetFPos(refNum = (*frHndl)->fileState.refNum, fsFromStart, 0)) return(err);
  1658.  
  1659.     if ((*frHndl)->fileState.sfType != MovieFileType) {
  1660.         if (!err) {        /* Read header info from file. */
  1661.             hstate = HGetState((Handle)frHndl);
  1662.             HLock((Handle)frHndl);
  1663.             ptr1   = (Ptr)&((*frHndl)->d.doc);
  1664.             ptr2   = (Ptr)&((*frHndl)->d.doc.fhInfo.endDocHeaderInfo);
  1665.             count  = (long)ptr2 - (long)ptr1;
  1666.             err    = FSRead(refNum, &count, ptr1);
  1667.             HSetState((Handle)frHndl, hstate);
  1668.             if (!err) {
  1669.                 vers = (*frHndl)->d.doc.fhInfo.version;
  1670.                 if ((vers < gMinVersion) || (vers > gMaxVersion))
  1671.                     err = kWrongVersion;
  1672.             }
  1673.         }
  1674.     }
  1675.  
  1676.     return(err);
  1677. }
  1678.  
  1679.  
  1680.  
  1681. /*****************************************************************************/
  1682.  
  1683.  
  1684.  
  1685. #pragma segment Window
  1686. OSErr    DefaultReadDocumentFixup(FileRecHndl frHndl)
  1687. {
  1688.     TreeObjHndl    root, undo, chndl;
  1689.  
  1690.     root = (*frHndl)->d.doc.root;
  1691.     undo = mDerefRoot(root)->undo;
  1692.     for (;;) {
  1693.         if (!(chndl = GetChildHndl(root, -1))) break;
  1694.         if ((*chndl)->type != UNDOTASKOBJ)     break;
  1695.         MoveChild(NO_EDIT, root, -1, undo, -1);
  1696.         mDerefUndo(undo)->undoDepth++;
  1697.             /* Move any undo tasks that were saved with the document
  1698.             ** out of the document and into the undo hierarchy. */
  1699.     }
  1700.  
  1701.     return(noErr);
  1702. }
  1703.  
  1704.  
  1705.  
  1706. /*****************************************************************************/
  1707.  
  1708.  
  1709.  
  1710. #pragma segment Window
  1711. OSErr    DoWriteDocument(FileRecHndl frHndl)
  1712. {
  1713.     WriteDocumentProcPtr    proc;
  1714.     OSErr                    err;
  1715.  
  1716.     err = noErr;
  1717.     if (proc = (*frHndl)->fileState.writeDocumentProc)
  1718.         err = (*proc)(frHndl);
  1719.     return(err);
  1720. }
  1721.  
  1722.  
  1723.  
  1724. /*****************************************************************************/
  1725.  
  1726.  
  1727.  
  1728. #pragma segment Window
  1729. OSErr    DoWriteDocumentHeader(FileRecHndl frHndl)
  1730. {
  1731.     WriteDocumentHeaderProcPtr    proc;
  1732.     OSErr                        err;
  1733.  
  1734.     err = noErr;
  1735.     if (proc = (*frHndl)->fileState.writeDocumentHeaderProc)
  1736.         err = (*proc)(frHndl);
  1737.     return(err);
  1738. }
  1739.  
  1740.  
  1741.  
  1742. /*****************************************************************************/
  1743.  
  1744.  
  1745.  
  1746. #pragma segment Window
  1747. OSErr    DefaultWriteDocument(FileRecHndl frHndl)
  1748. {
  1749.     short        refNum, cnum, numSaveUndos;
  1750.     OSErr        err;
  1751.     long        fpos;
  1752.     TreeObjHndl    root, undo, chndl;
  1753.  
  1754.     refNum = (*frHndl)->fileState.refNum;
  1755.     err    = DoWriteDocumentHeader(frHndl);
  1756.  
  1757.     if (!err) {
  1758.         if ((*frHndl)->fileState.sfType != MovieFileType) {
  1759.             undo         = GetUndoHndl(root = (*frHndl)->d.doc.root);
  1760.             numSaveUndos = mDerefUndo(undo)->numSaveUndos;
  1761.             for (cnum = mDerefUndo(undo)->undoDepth; ((cnum) && (numSaveUndos)); --numSaveUndos)
  1762.                 MoveChild(NO_EDIT, undo, --cnum, root, -1);
  1763.                     /* Move the designated number of undo tasks into the document side.
  1764.                     ** They will be saved to disk this way.  The designated number may be
  1765.                     ** zero, which means that undos aren't saved to disk. */
  1766.  
  1767.             DoNumberTree(root);
  1768.                 /* Assign each object in the tree a unique treeID.  This will allow
  1769.                 ** the objects to convert handle references into ID references so that
  1770.                 ** the data can be saved to disk. */
  1771.  
  1772.             err = WriteTree(root, refNum);
  1773.                 /* Write out the hierarchical data.  This includes the data in the root object.
  1774.                 ** When reading a data file, the root object data has already been initialized,
  1775.                 ** and therefore reading in the old root data from disk is a bad thing.  This is
  1776.                 ** handled by caching the root data prior to reading in a file, and then
  1777.                 ** restoring the data after the ReadTree() call has been made. */
  1778.  
  1779.             for (;;) {
  1780.                 if (!(chndl = GetChildHndl(root, -1))) break;
  1781.                 if ((*chndl)->type != UNDOTASKOBJ)     break;
  1782.                 MoveChild(NO_EDIT, root, -1, undo, cnum++);
  1783.                     /* Move any undo tasks that we previously moved into the document
  1784.                     ** out of the document and back into the undo hierarchy. */
  1785.             }
  1786.  
  1787.             if (!err) {
  1788.                 err = GetFPos(refNum, &fpos);
  1789.                 if (!err)
  1790.                     err = SetEOF(refNum, fpos);
  1791.             }            /* The document may be shorter than last time it was written to disk.
  1792.                         ** Handle this case by ending the file based on the new length. */
  1793.         }
  1794.         else {
  1795.         }
  1796.     }
  1797.  
  1798.     return(err);
  1799. }
  1800.  
  1801.  
  1802.  
  1803. /*****************************************************************************/
  1804.  
  1805.  
  1806.  
  1807. #pragma segment Window
  1808. OSErr    DefaultWriteDocumentHeader(FileRecHndl frHndl)
  1809. {
  1810.     short        refNum;
  1811.     OSErr        err;
  1812.     WindowPtr    window;
  1813.     char        hstate;
  1814.     Ptr            ptr1, ptr2;
  1815.     long        count;
  1816.  
  1817.     if (err = SetFPos(refNum = (*frHndl)->fileState.refNum, fsFromStart, 0)) return(err);
  1818.  
  1819.     if ((*frHndl)->fileState.sfType != MovieFileType) {
  1820.         if (window = (*frHndl)->fileState.window) {
  1821.             if (!(*frHndl)->fileState.readOnly) {
  1822.                 (*frHndl)->d.doc.fhInfo.structureRect = GetWindowStructureRect(window);
  1823.                 (*frHndl)->d.doc.fhInfo.contentRect   = GetWindowContentRect(window);
  1824.                 (*frHndl)->d.doc.fhInfo.stdState      = mDerefWStateData(window)->stdState;
  1825.                 (*frHndl)->d.doc.fhInfo.userState     = mDerefWStateData(window)->userState;
  1826.             }
  1827.         }
  1828.         else SetRect(&(*frHndl)->d.doc.fhInfo.structureRect, 0, 0, 0, 0);
  1829.         hstate = HGetState((Handle)frHndl);
  1830.         HLock((Handle)frHndl);
  1831.         ptr1   = (Ptr)&((*frHndl)->d.doc);
  1832.         ptr2   = (Ptr)&((*frHndl)->d.doc.fhInfo.endDocHeaderInfo);
  1833.         count  = (long)ptr2 - (long)ptr1;
  1834.         err    = FSWrite(refNum, &count, ptr1);
  1835.         HSetState((Handle)frHndl, hstate);
  1836.     }
  1837.  
  1838.     return(err);
  1839. }
  1840.  
  1841.  
  1842.  
  1843. /*****************************************************************************/
  1844.  
  1845.  
  1846.  
  1847. #pragma segment Window
  1848. void    DoResizeContent(WindowPtr window, short oldh, short oldv)
  1849. {
  1850.     FileRecHndl                frHndl;
  1851.     ResizeContentProcPtr    proc;
  1852.  
  1853.     if (IsAppWindow(window))
  1854.         if (frHndl = (FileRecHndl)GetWRefCon(window))
  1855.             if (proc = (*frHndl)->fileState.resizeContentProc)
  1856.                 (*proc)(window, oldh, oldv);
  1857. }
  1858.  
  1859.  
  1860.  
  1861. /*****************************************************************************/
  1862.  
  1863.  
  1864.  
  1865. #pragma segment Window
  1866. void    DoScrollFrame(WindowPtr window, long dh, long dv)
  1867. {
  1868.     FileRecHndl            frHndl;
  1869.     ScrollFrameProcPtr    proc;
  1870.  
  1871.     if (window) {
  1872.         frHndl = (FileRecHndl)GetWRefCon(window);
  1873.         if (proc = (*frHndl)->fileState.scrollFrameProc)
  1874.             (*proc)(frHndl, window, dh, dv);
  1875.     }
  1876. }
  1877.  
  1878.  
  1879.  
  1880. /*****************************************************************************/
  1881.  
  1882.  
  1883.  
  1884. #pragma segment Window
  1885. void    DoUndoFixup(FileRecHndl frHndl, Point contOrg, Boolean afterUndo)
  1886. {
  1887.     UndoFixupProcPtr    proc;
  1888.  
  1889.     if (proc = (*frHndl)->fileState.undoFixupProc)
  1890.         (*proc)(frHndl, contOrg, afterUndo);
  1891. }
  1892.  
  1893.  
  1894.  
  1895. /*****************************************************************************/
  1896. /*****************************************************************************/
  1897.  
  1898.  
  1899.  
  1900. #pragma segment Window
  1901. WindowPtr    GetOldLocWindow(short id, Ptr storage, Boolean vis, WindowPtr relWindow,
  1902.                             WindowPtr behind, Boolean inColor, Rect sizeInfo, long refCon)
  1903. {
  1904.     return(GetSomeKindOfWindow(OldLocWindow, id, storage, vis, relWindow,
  1905.                                behind, inColor, sizeInfo, refCon));
  1906. }
  1907.  
  1908.  
  1909.  
  1910. /*****************************************************************************/
  1911.  
  1912.  
  1913.  
  1914. /* Open a window where it was stored at.  This would be simple, except for the
  1915. ** complication that the user may be opening the document on a different Mac
  1916. ** that doesn't have the same monitor configuration.  Due to this, we need to
  1917. ** make sure that the window doesn't open completely out of view. */
  1918.  
  1919. #pragma segment Window
  1920. static Rect    OldLocWindow(WindowPtr window, WindowPtr relatedWindow, Rect sizeInfo)
  1921. {
  1922.     FileRecHndl    frHndl;
  1923.     RgnHandle    rgn;
  1924.     Rect        rct, bbox, srct, crct;
  1925.     short        attributes, hDocSize, vDocSize, dh, dv, h, v;
  1926.  
  1927.     frHndl     = (FileRecHndl)GetWRefCon(window);
  1928.     attributes = (*frHndl)->fileState.attributes;
  1929.  
  1930.     if (hDocSize = (*frHndl)->d.doc.fhInfo.hDocSize) {
  1931.         hDocSize += (*frHndl)->fileState.leftSidebar;
  1932.         if (attributes & kwHScroll)
  1933.             hDocSize += 15;
  1934.     }
  1935.     if (vDocSize = (*frHndl)->d.doc.fhInfo.vDocSize) {
  1936.         vDocSize += (*frHndl)->fileState.topSidebar;
  1937.         if (attributes & kwVScroll)
  1938.             vDocSize += 15;
  1939.     }
  1940.  
  1941.     srct = (*frHndl)->d.doc.fhInfo.structureRect;
  1942.     crct = (*frHndl)->d.doc.fhInfo.contentRect;
  1943.     if (EmptyRect(&srct)) {
  1944.         SetRect(&sizeInfo, hDocSize, vDocSize, hDocSize, vDocSize);
  1945.         return(StaggerWindow(window, relatedWindow, sizeInfo));
  1946.     }
  1947.  
  1948.     rct = srct;
  1949.     rct.bottom = crct.top;
  1950.  
  1951.     RectRgn(rgn = NewRgn(), &rct);
  1952.     SectRgn(rgn, GetGrayRgn(), rgn);
  1953.     bbox = (*rgn)->rgnBBox;
  1954.     DisposeRgn(rgn);
  1955.  
  1956.     if (EqualRect(&rct, &bbox)) {
  1957.         rct = (*frHndl)->d.doc.fhInfo.contentRect;
  1958.         SizeWindow(window, rct.right - rct.left, rct.bottom - rct.top, false);
  1959.         MoveWindow(window, rct.left, rct.top, false);
  1960.         mDerefWStateData(window)->stdState  = (*frHndl)->d.doc.fhInfo.stdState;
  1961.         mDerefWStateData(window)->userState = (*frHndl)->d.doc.fhInfo.userState;
  1962.         return(rct);
  1963.     }
  1964.  
  1965.     rct = srct;
  1966.     if (!(dh = bbox.left - rct.left))
  1967.         dh = bbox.right  - rct.right;
  1968.     if (!(dv = bbox.top  - rct.top))
  1969.         dv = bbox.bottom - rct.bottom;
  1970.     OffsetRect(&rct, dh, dv);
  1971.  
  1972.     RectRgn(rgn = NewRgn(), &rct);
  1973.     SectRgn(rgn, GetGrayRgn(), rgn);
  1974.     bbox = (*rgn)->rgnBBox;
  1975.     DisposeRgn(rgn);
  1976.  
  1977.     if (EqualRect(&rct, &bbox)) {
  1978.         h = crct.right  - crct.left;
  1979.         v = crct.bottom - crct.top;
  1980.     }
  1981.     else {
  1982.         h = hDocSize;
  1983.         v = vDocSize;
  1984.     }
  1985.     SetRect(&sizeInfo, h, v, h, v);
  1986.  
  1987.     return(StaggerWindow(window, relatedWindow, sizeInfo));
  1988.         /* Force window as big as possible for this screen and data size. */
  1989. }
  1990.  
  1991.  
  1992.  
  1993. /*****************************************************************************/
  1994.  
  1995.  
  1996.  
  1997. #pragma segment Window
  1998. void    CleanSendBehind(WindowPtr window, WindowPtr afterWindow)
  1999. {
  2000.     WindowPtr    oldPort;
  2001.     Point        offset;
  2002.     RgnHandle    contRgn, keepContRgn, visRgn;
  2003.  
  2004.     if (afterWindow == (WindowPtr)-1) {
  2005.         BringToFront(window);
  2006.         HiliteWindows();
  2007.         return;
  2008.     }
  2009.  
  2010.     GetPort(&oldPort);
  2011.     SetPort(window);
  2012.     offset.h = offset.v = 0;
  2013.     LocalToGlobal(&offset);
  2014.     SetPort(window);
  2015.  
  2016.     CopyRgn(contRgn = ((WindowPeek)window)->contRgn, keepContRgn = NewRgn());
  2017.     OffsetRgn(visRgn = window->visRgn, offset.h, offset.v);
  2018.     DiffRgn(contRgn, visRgn, contRgn);
  2019.     OffsetRgn(visRgn, -offset.h, -offset.v);
  2020.         /* Don't allow PaintOne to touch the part of the window already visible. */
  2021.  
  2022.     SendBehind(window, afterWindow);
  2023.         /* Do the SendBehind.  Since the content region is way off the
  2024.         ** screen(s), no erasing of the content of the window will occur. */
  2025.  
  2026.     CopyRgn(keepContRgn, contRgn);
  2027.     DisposeRgn(keepContRgn);
  2028.  
  2029.     CalcVis((WindowPeek)window);
  2030.         /* One negative to the content region games is that the visRgn gets
  2031.         ** calculated incorrectly when SendBehind() is called.  The call to
  2032.         ** CalcVis() fixes this problem. */
  2033.  
  2034.     HiliteWindows();
  2035. }
  2036.  
  2037.  
  2038.  
  2039. /*****************************************************************************/
  2040.  
  2041.  
  2042.  
  2043. #pragma segment Window
  2044. void    CleanSendInFront(WindowPtr window, WindowPtr beforeWindow)
  2045. {
  2046.     beforeWindow = GetPreviousWindow(beforeWindow);
  2047.     CleanSendBehind(window, beforeWindow);
  2048. }
  2049.  
  2050.  
  2051.  
  2052. /*****************************************************************************/
  2053.  
  2054.  
  2055.  
  2056. #pragma segment Window
  2057. void    HiliteWindows(void)
  2058. {
  2059.     WindowPtr    window;
  2060.     FileRecHndl    frHndl;
  2061.     short        thisKind, lastKind;
  2062.  
  2063.     lastKind = -1;            /* No such kind. */
  2064.  
  2065.     for (window = FrontWindow(); window; window = (WindowPtr)(((WindowPeek)window)->nextWindow)) {
  2066.  
  2067.         if (!((WindowPeek)window)->visible) continue;
  2068.  
  2069.         thisKind = kwIsDocument;
  2070.         if (IsAppWindow(window)) {
  2071.             frHndl   = (FileRecHndl)GetWRefCon(window);
  2072.             thisKind = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  2073.         }
  2074.  
  2075.         if (gInBackground)
  2076.             lastKind = thisKind;
  2077.                 /* If application moved to background, we want to turn all hilighting off
  2078.                 ** for all windows.  This is accomplished by pretending that the kind of
  2079.                 ** the current window is the same as the kind of the last window. */
  2080.  
  2081.         if (thisKind != lastKind) {
  2082.             if (!((WindowPeek)window)->hilited) {
  2083.                 HiliteWindow(window, true);
  2084.                 DoActivate(window);
  2085.             }
  2086.             lastKind = thisKind;
  2087.         }
  2088.         else {
  2089.             if (((WindowPeek)window)->hilited) {
  2090.                 HiliteWindow(window, false);
  2091.                 DoActivate(window);
  2092.             }
  2093.         }
  2094.     }
  2095. }
  2096.  
  2097.  
  2098.  
  2099. /*****************************************************************************/
  2100.  
  2101.  
  2102.  
  2103. #pragma segment Window
  2104. void    UnhiliteWindows(void)
  2105. {
  2106.     WindowPtr    window;
  2107.  
  2108.     for (window = nil; window = GetNextWindow(window, 0);) {
  2109.         if (!((WindowPeek)window)->visible) continue;
  2110.         if (((WindowPeek)window)->windowKind <= dialogKind) continue;
  2111.         if (((WindowPeek)window)->hilited) {
  2112.             HiliteWindow(window, false);
  2113.             DoActivate(window);
  2114.         }
  2115.     }
  2116. }
  2117.  
  2118.  
  2119.  
  2120. /*****************************************************************************/
  2121.  
  2122.  
  2123.  
  2124. /* This is called when an update event is received for a window.  First, the
  2125. ** updateRgn is separated into two parts.  Part 1 holds the window frame area,
  2126. ** if any.  This is the area that might hold the scrollbars, grow icon, and
  2127. ** any other application-specific frame parts.  This is drawn first.  Once
  2128. ** this is done, the remainder of the updateRgn is drawn.  This allows us to
  2129. ** handle all of the frame clipping without using the clipRgn.  By freeing up
  2130. ** the clipRgn, we allow the application to use it without having to share. */
  2131.  
  2132. #pragma segment Window
  2133. void    DoUpdate(WindowPtr window)
  2134. {
  2135.     RgnHandle    contPart, framePart;
  2136.     Point        contOrg;
  2137.     FileRecHndl    frHndl;
  2138.  
  2139.     SetPort(window);
  2140.  
  2141.     if (IsAppWindow(window)) {
  2142.  
  2143.         DoUpdateSeparate(window, &contPart, &framePart);
  2144.  
  2145.         if (framePart) {        /* Update the document frame, if any. */
  2146.             CopyRgn(framePart, ((WindowPeek)window)->updateRgn);
  2147.             DisposeRgn(framePart);
  2148.             ++gBeginUpdateNested;
  2149.             BeginUpdate(window);
  2150.             DoDrawFrame(window);
  2151.             EndUpdate(window);
  2152.             --gBeginUpdateNested;
  2153.         }
  2154.         if (contPart) {            /* Update the rest of the content. */
  2155.             CopyRgn(contPart, ((WindowPeek)window)->updateRgn);
  2156.             DisposeRgn(contPart);
  2157.             ++gBeginUpdateNested;
  2158.             BeginUpdate(window);
  2159.             GetContentOrigin(window, &contOrg);
  2160.             SetOrigin(contOrg.h, contOrg.v);
  2161.             frHndl = (FileRecHndl)GetWRefCon(window);
  2162.             DoImageDocument(frHndl);
  2163.             SetOrigin(0, 0);
  2164.             EndUpdate(window);
  2165.             --gBeginUpdateNested;
  2166.         }
  2167.     }
  2168. }
  2169.  
  2170.  
  2171.  
  2172. /*****************************************************************************/
  2173.  
  2174.  
  2175.  
  2176. #pragma segment Window
  2177. void    DoSetCursor(Cursor *cursor)
  2178. {
  2179.     gCursorPtr = nil;
  2180.  
  2181.     if (cursor)
  2182.         SetCursor(cursor);
  2183.  
  2184.     if (!cursor)
  2185.         DoCursor();
  2186. }
  2187.  
  2188.  
  2189.  
  2190. /*****************************************************************************/
  2191.  
  2192.  
  2193.  
  2194. #pragma segment Window
  2195. CursPtr    DoSetResCursor(short crsrID)
  2196. {
  2197.     CursHandle    crsr;
  2198.  
  2199.     gCursorPtr = nil;
  2200.  
  2201.     crsr = GetCursor(crsrID);
  2202.     if (crsr) {
  2203.         gCursor = **crsr;
  2204.         DoSetCursor(&gCursor);
  2205.         return(&gCursor);
  2206.     }
  2207.  
  2208.     SetCursor(&qd.arrow);
  2209.     return(&qd.arrow);
  2210. }
  2211.  
  2212.  
  2213.  
  2214. /*****************************************************************************/
  2215.  
  2216.  
  2217.  
  2218. #pragma segment Window
  2219. void    DoWindowCursor(void)
  2220. {
  2221.     WindowPeek            wpeek;
  2222.     WindowPtr            window;
  2223.     Point                mouseLoc;
  2224.     FileRecHndl            frHndl;
  2225.     RgnHandle            srgn;
  2226.     WindowCursorProcPtr    proc;
  2227.  
  2228.     if (gInBackground) return;
  2229.         /* Don't change cursors if we aren't the front application. */
  2230.  
  2231.     if (!gCursorRgn)
  2232.         gCursorRgn = NewRgn();
  2233.  
  2234.     wpeek = (WindowPeek)FrontWindow();
  2235.     if (!IsAppWindow((WindowPtr)wpeek)) {
  2236.         SetRectRgn(gCursorRgn, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos);
  2237.         SetCursor(gCursorPtr = &qd.arrow);
  2238.     }        /* Non-application windows get an arrow cursor. */
  2239.  
  2240.     mouseLoc = GetGlobalMouse();
  2241.  
  2242.     if (gCursorPtr) {                            /* Do we already have a cursor... */
  2243.         if (PtInRgn(mouseLoc, gCursorRgn)) {    /* Are we still in the cursor area... */
  2244.             SetCursor(gCursorPtr);                /* Then set it to that. */
  2245.             return;
  2246.         }
  2247.     }
  2248.  
  2249.     SetRectRgn(gCursorRgn, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos);
  2250.  
  2251.     for (wpeek = (WindowPeek)FrontWindow();; wpeek = wpeek->nextWindow) {
  2252.  
  2253.         if (!IsAppWindow((WindowPtr)wpeek)) break;
  2254.  
  2255.         if (!wpeek->visible) continue;        /* No cursors for invisible windows. */
  2256.  
  2257.         window = (WindowPtr)wpeek;
  2258.         srgn   = wpeek->strucRgn;
  2259.         frHndl = (FileRecHndl)GetWRefCon(window);
  2260.  
  2261.         if (!(proc = (*frHndl)->fileState.windowCursorProc)) {
  2262.             if (PtInRgn(mouseLoc, srgn)) {
  2263.                 SectRgn(gCursorRgn, srgn, gCursorRgn);
  2264.                 SetCursor(gCursorPtr = &qd.arrow);
  2265.                 return;
  2266.             }
  2267.         }
  2268.         else if ((*proc)(frHndl, window, mouseLoc)) return;
  2269.  
  2270.         DiffRgn(gCursorRgn, srgn, gCursorRgn);
  2271.     }
  2272.  
  2273.     SetCursor(gCursorPtr = &qd.arrow);
  2274. }
  2275.  
  2276.  
  2277.  
  2278. /*****************************************************************************/
  2279.  
  2280.  
  2281.  
  2282. #pragma segment Window
  2283. WindowPtr    FrontWindowOfType(short wkind)
  2284. {
  2285.     WindowPtr    window;
  2286.     FileRecHndl    frHndl;
  2287.     short        wk;
  2288.  
  2289.     for (window = nil; window = GetNextWindow(window, 0);) {
  2290.         if (frHndl = (FileRecHndl)GetWRefCon(window)) {
  2291.             wk = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  2292.             if (wkind == wk) return(window);
  2293.         }
  2294.     }
  2295.  
  2296.     return(nil);
  2297. }
  2298.  
  2299.  
  2300.  
  2301. /*****************************************************************************/
  2302.  
  2303.  
  2304.  
  2305. #pragma segment Window
  2306. short    HCenteredAlert(short alertID, WindowPtr relatedWindow, ModalFilterProcPtr filter)
  2307. {
  2308.     short    itemHit;
  2309.  
  2310.     UnhiliteWindows();
  2311.     itemHit = CenteredAlert(alertID, relatedWindow, filter);
  2312.     HiliteWindows();
  2313.     return(itemHit);
  2314. }
  2315.  
  2316.  
  2317.  
  2318.